package com.ctg.itrdc.imageconsole.service.image;

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;
import javax.ws.rs.core.Response;

import org.json.JSONArray;
import org.json.JSONObject;
import org.springframework.stereotype.Component;

import com.ctg.itrdc.imageconsole.common.constants.DockerConstant;
import com.ctg.itrdc.imageconsole.common.constants.DockerConstant.DockerImageCons;
import com.ctg.itrdc.imageconsole.common.util.PropertiesUtils;
import com.ctg.itrdc.imageconsole.common.util.TimeUtils;
import com.ctg.itrdc.imageconsole.data.dao.IDockerImageDao;
import com.ctg.itrdc.imageconsole.data.dao.IDockerImageTagDao;
import com.ctg.itrdc.imageconsole.data.dao.IDockerMicroUserDao;
import com.ctg.itrdc.imageconsole.data.dao.IUserImageShareDao;
import com.ctg.itrdc.imageconsole.data.dto.image.MicroUserDTO;
import com.ctg.itrdc.imageconsole.data.dto.image.RepositoryDTO;
import com.ctg.itrdc.imageconsole.data.dto.image.TagShareDTO;
import com.ctg.itrdc.imageconsole.data.entity.DockerImage;
import com.ctg.itrdc.imageconsole.data.entity.DockerImageTag;
import com.ctg.itrdc.imageconsole.data.entity.UserImageShare;
import com.ctg.itrdc.imageconsole.data.entity.user.DockerMicroUser;
import com.ctg.itrdc.imageconsole.util.AuthorizationUtil;
import com.ctg.itrdc.imageconsole.util.HarborUtil;
import com.ctg.itrdc.pasp.security.utils.WebUtils;
import com.ctg.itrdc.paspsdk.common.entity.PageInfo;

@Component
public class ImageService {

	private static String configProperties = "config.properties";
	
	@Resource
	IDockerImageDao dockerImageDao;
	
	@Resource
	IDockerImageTagDao imageTagDao;
	
	@Resource
	IUserImageShareDao userImageShareDao;
	
	@Resource
	IDockerMicroUserDao microUserDao;
	
	
	public PageInfo<RepositoryDTO> getRepositories(String imageType, String sysUserCode, Integer pageNum, Integer pageSize) {
		String harbor = PropertiesUtils.getConfigValueCache(configProperties, "harbor.vip");
		String harborUserName = PropertiesUtils.getConfigValueCache(configProperties, "harbor.username");
		String harborPassword = PropertiesUtils.getConfigValueCache(configProperties, "harbor.password");
		String token = AuthorizationUtil.getBasicToken(harborUserName, harborPassword);
		
		JSONArray projects = null;
		JSONObject project = null;
		if (DockerImageCons.BASE.equals(imageType)) {// 基础镜像
			projects = HarborUtil.getProjects(harbor, token, "library");
			for(int i = 0; i < projects.length(); i++) {
				if("library".equals(projects.getJSONObject(i).getString("name"))) {
					project = projects.getJSONObject(i);
					break;
				}
			}
		} else if (DockerImageCons.BUILD.equals(imageType)) {// 用户自己构建的镜像
			projects = HarborUtil.getProjects(harbor, token, sysUserCode);
			for(int i = 0; i < projects.length(); i++) {
				if(sysUserCode.equals(projects.getJSONObject(i).getString("name"))) {
					project = projects.getJSONObject(i);
					break;
				}
			}
		}  else if (DockerImageCons.SHARE.equals(imageType)) {// 共享镜像
			long currentUserId = WebUtils.getCtgUser().getSysUserId();
			return userImageShareDao.getImagesOfShare(currentUserId, pageNum, pageSize);
		}
		if (project==null) {
			return new PageInfo<>();
		}
		Long projectId = project.getLong("project_id");
		
		// get repositories from harbor by project_id 
		Response responseRepositories = HarborUtil.getRepositories(harbor, token, projectId, pageNum, pageSize);
		JSONArray repositories = new JSONArray(responseRepositories.readEntity(String.class));
		List<String> repositoriesInList = new ArrayList<>();
		for(int i = 0; i < repositories.length(); i++){
			repositoriesInList.add(repositories.getString(i));
			if (!imageIsExist(repositories.getString(i))) {
				saveImageFile(imageType, repositories.getString(i));	
			}
		}
		PageInfo<RepositoryDTO> pageInfo = new PageInfo<>();
		pageInfo.setPageNum(pageNum);
		pageInfo.setPageSize(pageSize);
		pageInfo.setTotal(new Integer(responseRepositories.getHeaderString("X-Total-Count")));
		pageInfo.setList(new ArrayList<RepositoryDTO>());
		
		for(String repository : repositoriesInList) {			
			RepositoryDTO repositoryDTO = new RepositoryDTO();
			repositoryDTO.setImageName(repository);
			repositoryDTO.setRepositoryAddress(harbor);
			pageInfo.getList().add(repositoryDTO);						
		}
		return pageInfo;
	}
	
	public List<DockerImageTag> getTags(String imageType, String repository) {
		if (DockerImageCons.SHARE.equals(imageType)) {
			List<UserImageShare> userImageShares = userImageShareDao.getSharesByUserId(WebUtils.getCtgUser().getSysUserId());
			
			Map<Long, Long> tagIdMap = new LinkedHashMap<>();
			for(UserImageShare imageShare : userImageShares){
				tagIdMap.put(imageShare.getDockerImageTagId(), imageShare.getRelateUserId());
			}
			return imageTagDao.selectByTagIdMap(repository, tagIdMap);
		}
		String userCode = WebUtils.getCtgUser().getSysUserCode();
		
		// get docker_micro_user 
		DockerMicroUser microUser = microUserDao.selectByCode(userCode);
		if(null == microUser)
			throw new RuntimeException(String.format("Error : selecting docker_micro_user by userCode %s returns null", userCode));

		// get tags from harbor
		String harbor = PropertiesUtils.getConfigValueCache(configProperties, "harbor.vip");
		String harborUserName = PropertiesUtils.getConfigValueCache(configProperties, "harbor.username");
		String harborPassword = PropertiesUtils.getConfigValueCache(configProperties, "harbor.password");
		String token = AuthorizationUtil.getBasicToken(harborUserName, harborPassword);
		
		JSONArray tags = HarborUtil.getTags(harbor, token, repository);
		List<String> tagsInList = new ArrayList<>();
		for(int i = 0; i < tags.length(); i++){
			tagsInList.add(tags.getString(i));
			if (!imageIndexIsExist(repository, tags.getString(i))) {
				saveImageTag(repository, tags.getString(i));
			}
		}
		return imageTagDao.selectByImageName(repository);
	}
	
	
	private Long saveImageFile(String imageType, String imageName) {
		Long userId = WebUtils.getCtgUser().getSysUserId();
		DockerImage imageFile = new DockerImage();
		imageFile.setImageName(imageName);
		imageFile.setCreateUserId(userId);
		imageFile.setLastUpdateUserId(userId);
		imageFile.setCreateTime(TimeUtils.getNowDateStr());
		imageFile.setLastUpdateTime(TimeUtils.getNowDateStr());
		imageFile.setState(DockerConstant.DockerImageCons.NORMAL);
		imageFile.setImageType(imageType);

		Long id = (long) dockerImageDao.insert(imageFile);
		return id;
	}
	
	
	private void saveImageTag(String imageName, String tag){
		DockerImage image = queryByImageName(imageName);
		
		Long userId = WebUtils.getCtgUser().getSysUserId();
		DockerImageTag imageIndex = new DockerImageTag();
		imageIndex.setDockerImageId(image.getId());
		imageIndex.setImageName(imageName);
		imageIndex.setTag(tag);
		imageIndex.setState(DockerConstant.DockerImageIndexCons.NORMAL);
		imageIndex.setSource(DockerConstant.DockerImageIndexCons.BUILD);
		imageIndex.setCreateUserId(userId);
		imageIndex.setLastUpdateUserId(userId);
		imageIndex.setCreateTime(TimeUtils.getNowDateStr());
		imageIndex.setLastUpdateTime(TimeUtils.getNowDateStr());

		imageTagDao.insert(imageIndex);
	}
	
	private boolean imageIsExist(String imageName){
		DockerImage image = queryByImageName(imageName);
		if (image != null) {
			return true;
		} else {
			return false;
		}
		
	}
	
	private DockerImage queryByImageName(String imageName) {
		DockerImage image = new DockerImage();
		image.setImageName(imageName);
		List<DockerImage> images = dockerImageDao.selectByExample(image);
		if (images != null && images.size()>0) {
			return images.get(0);
		} else {
			return null;
		}
	} 
	
	private boolean imageIndexIsExist(String imageName, String tag){
		DockerImageTag imageIndex = imageTagDao.selectByImageNameAndVersion(imageName, tag);
		if (imageIndex != null) {
			return true;
		} else {
			return false;
		}
	}
	
	public void tagShare(TagShareDTO tagShareDTO) {
		Long currentUserId = WebUtils.getCtgUser().getSysUserId();
		
		UserImageShare userImageShare = new UserImageShare();
		userImageShare.setRelateUserId(currentUserId);
		userImageShare.setDockerImageTagId(tagShareDTO.getDockerImageTagId());
		// 每次都先删除该镜像版本与所有共享用户、被共享用户之间的关联记录
		userImageShareDao.deleteByTagIdAndRelateUserId(tagShareDTO.getDockerImageTagId(), currentUserId);
		if (tagShareDTO.getSysUserIds() == null) {
			return;
		}
		for(Long sysUserId:tagShareDTO.getSysUserIds()){
			userImageShare.setUserId(sysUserId);
			// 新增该镜像版本与所有共享用户、被共享用户之间的关联记录
			userImageShareDao.insert(userImageShare);
		}
	}
	
	
	public List<MicroUserDTO> getTagShares(Long dockerImageTagId) {
		Long currentUserId = WebUtils.getCtgUser().getSysUserId();
		
		UserImageShare userImageShare = new UserImageShare();
		userImageShare.setRelateUserId(currentUserId);
		userImageShare.setDockerImageTagId(dockerImageTagId);
		
		List<UserImageShare> shares = userImageShareDao.selectByExample(userImageShare);
		
		List<MicroUserDTO> shareDTOs = new ArrayList<>();
		
		for(UserImageShare share : shares) {
			DockerMicroUser microUser = new DockerMicroUser();
			microUser.setSysUserId(share.getUserId());
			microUser.setAvailable(1);
			microUser = microUserDao.selectByExample(microUser).get(0);
			
			MicroUserDTO shareDTO = new MicroUserDTO();
			shareDTO.setCode(microUser.getCode());
			shareDTO.setName(microUser.getName());
			shareDTO.setSysUserId(microUser.getSysUserId());
			
			shareDTOs.add(shareDTO);
		}
		
		return shareDTOs;
	}

}
